JavaScript 56.7%
TypeScript 42.6%
1import { NextRequest, NextResponse } from "next/server";2import { prisma } from "@/lib/prisma";3import { getThumbnail, loadFileData } from "@/lib/storage";45// Largeurs autorisées pour les rendus redimensionnés (évite la génération arbitraire)6const ALLOWED_WIDTHS = [200, 400, 800, 1280, 2048];78export async function GET(9 request: NextRequest,10 { params }: { params: { id: string } }11) {12 const file = await prisma.file.findUnique({ where: { id: params.id } });1314 if (!file) {15 return NextResponse.json({ error: "File not found" }, { status: 404 });16 }1718 // --- Rendu image redimensionné (miniature / version viewer) ---19 const wParam = request.nextUrl.searchParams.get("w");20 if (wParam && file.mimeType.startsWith("image/") && file.mimeType !== "image/svg+xml") {21 const requested = parseInt(wParam, 10);22 const width =23 ALLOWED_WIDTHS.find((w) => w >= requested) ??24 ALLOWED_WIDTHS[ALLOWED_WIDTHS.length - 1];25 try {26 const webp = await getThumbnail(file.storagePath, file.id, width, file.isEncrypted);27 return new NextResponse(new Uint8Array(webp), {28 headers: {29 "Content-Type": "image/webp",30 "Content-Length": String(webp.length),31 // Miniatures quasi-immuables (clé = id+largeur), cache agressif navigateur32 "Cache-Control": "private, max-age=604800",33 },34 });35 } catch {36 // En cas d'échec sharp on retombe sur l'original ci-dessous37 }38 }3940 // --- Fichier original (déchiffré au repos) ---41 const data = await loadFileData(file.storagePath, file.isEncrypted);4243 return new NextResponse(new Uint8Array(data), {44 headers: {45 "Content-Type": file.mimeType,46 "Content-Disposition": `inline; filename="${encodeURIComponent(file.name)}"`,47 "Content-Length": String(data.length),48 "Cache-Control": "private, max-age=3600",49 },50 });51}52